﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Diagnostics;
using System.IO;

namespace PcInfoLibrary
{

    //http://localhost:50303/PcInfoWebSite/PcInfoService.svc?wsdl
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together.
    public class PcInfoService : IPcInfoService
    {
        private static DateTime _startupTime;
        private bool _isShutdownRequested;
        private string _pathMeineSaveTvAufnahmen;
        private string _pathSavetvNochZuGucken;
        private string _pathMarkedLookedFiles;

        static PcInfoService()
        {
            _startupTime = DateTime.Now;

            // Create the source, if it does not already exist.
            if (!EventLog.SourceExists("PcInfoServiceSource"))
            {
                //An event log source should not be created and immediately used.
                //There is a latency time to enable the source, it should be created
                //prior to executing the application that uses the source.
                //Execute this sample a second time to use the new source.
                EventLog.CreateEventSource("PcInfoServiceSource", "PcInfoLog");
                Console.WriteLine("CreatedEventSource");
                Console.WriteLine("Exiting, execute the application a second time to use the source.");
                // The source is created.  Exit the application to allow it to be registered.
                return;
            }


        }

        public PcInfoService()
        {
            _pathMeineSaveTvAufnahmen = "C:\\Meine Save.TV-Aufnahmen";
            _pathSavetvNochZuGucken = "C:\\SaveTv\\noch zu gucken";
            _pathMarkedLookedFiles = "C:\\SaveTv\\geguckt";
            WriteEventLog("Service startup");
        }

        private static void WriteEventLog(string message)
        {
            // Create an EventLog instance and assign its source.
            var myLog = new EventLog {Source = "PcInfoServiceSource"};
            // Write an informational entry to the event log.    
            myLog.WriteEntry(message);
        }

        public TimeSpan GetPCStartUpTime()
        {
            try
            {
                var mo = new ManagementObject(@"\\.\root\cimv2:Win32_OperatingSystem=@");
                DateTime lastBootUp = ManagementDateTimeConverter.ToDateTime(mo["LastBootUpTime"].ToString());
                return DateTime.Now.ToUniversalTime() - lastBootUp.ToUniversalTime();
            }
            catch (Exception exc)
            {
                ThrowFaultException("Getting startuptime failed.", exc);
            }

            return TimeSpan.MinValue;
        }

        private static void ThrowFaultException(string message, Exception exc)
        {
            WriteErrorLog(exc);
            throw new FaultException<UserFriendlyError>(new UserFriendlyError()
                                                            {Message = message});
        }

        public List<FileEntry> GetMarkedLookedFiles()
        {
            try
            {
                DirectoryInfo info = new DirectoryInfo(_pathMarkedLookedFiles);

                var list = new List<FileEntry>();

                foreach (var file in info.EnumerateFiles("*.mp4", SearchOption.AllDirectories))
                {
                    list.Add(new FileEntry() { Name = file.Name, CreationTime = file.CreationTime, Path = file.FullName });
                }

                list.Sort(new Comparison<FileEntry>((x, y) =>
                {
                    return y.CreationTime.CompareTo(x.CreationTime);
                }));

                return list;
            }
            catch (Exception exc)
            {
                ThrowFaultException("Getting marked file information failed.", exc);
            }

            return null;
        }

        public void MarkFilesAsLooked(List<FileEntry> lookedFiles)
        {
            try
            {
                if (lookedFiles != null)
                {
                    foreach (var fileEntry in lookedFiles)
                    {
                        File.Move(fileEntry.Path, Path.Combine(_pathMarkedLookedFiles, Path.GetFileName(fileEntry.Path)));
                    }
                }
            }
            catch (Exception exc)
            {
                ThrowFaultException("Moving files failed", exc);
            }
        }

        public DateTime GetLastSystemShutdown()
        {
            try
            {
                string sKey = @"System\CurrentControlSet\Control\Windows";
                Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(sKey);
                string sValueName = "ShutdownTime";
                byte[] val = (byte[])key.GetValue(sValueName);
                long valueAsLong = BitConverter.ToInt64(val, 0);
                return DateTime.FromFileTime(valueAsLong);
            }
            catch (Exception exc)
            {
                ThrowFaultException("Getting last System Shutdown failed", exc);
            }

            return DateTime.MinValue;
        }

        public LogFile GetLogFile(string fileName)
        {
            try
            {
                // Create an instance of StreamReader to read from a file.
                // The using statement also closes the StreamReader.
                using (StreamReader sr = new StreamReader(Path.Combine(_logFileDirectory, fileName)))
                {
                    LogFile file = new LogFile();
                    file.Content = sr.ReadToEnd();
                    file.FileName = fileName;
                    return file;
                }
            }
            catch (Exception e)
            {
                // Let the user know what went wrong.
                ThrowFaultException("Getting LogFile failed", e);
            }

            return null;
        }

        private const string _logFileDirectory = "N:\\CopyJobs\\logs";

        public List<string> GetLogFileMetaData()
        {
            try
            {
                DirectoryInfo info = new DirectoryInfo(_logFileDirectory);
                FileInfo[] fileInfos = info.GetFiles("*.txt");

                List<string> infos = new List<string>();

                return infos;
            }
            catch (Exception exc)
            {

                ThrowFaultException("Getting log file meta data failed", exc);
            }

            return null;
        }

        public DateTime GetStartUpTime()
        {
            return _startupTime;
        }

        public void ShutDown()
        {
            WriteEventLog("Shutdown requested");

            _isShutdownRequested = true;

            try
            {
                Process.Start("shutdown", "/s /t 300");
            }
            catch (Exception exc)
            {
                ThrowFaultException("Shutdown failed", exc);
            }
        }

        private static void WriteErrorLog(Exception exc)
        {
            // Create an EventLog instance and assign its source.
            var myLog = new EventLog { Source = "PcInfoServiceSource" };
            myLog.WriteEntry(exc.Message, EventLogEntryType.Error);
        }

        public void CancelShutDown()
        {
            WriteEventLog("Shutdown canceled");

            try
            {
                Process.Start("shutdown", "/a");
                _isShutdownRequested = false;
            }
            catch (Exception exc)
            {
                ThrowFaultException("Cancel Shutdown failed", exc);
            }
        }

        public bool IsShutdownRequested()
        {
            return _isShutdownRequested;
        }

        public List<FileEntry> GetFileInformation()
        {
            try
            {
                var info = new DirectoryInfo(_pathMeineSaveTvAufnahmen);

                var list = new List<FileEntry>();

                foreach (var file in info.EnumerateFiles("*.mp4", SearchOption.TopDirectoryOnly))
                {
                    list.Add(new FileEntry() { Name = file.Name, CreationTime = file.CreationTime, Path = file.FullName });
                }

                list.Sort(new Comparison<FileEntry>((x, y) =>
                {
                    return y.CreationTime.CompareTo(x.CreationTime);
                }));

                return list;
            }
            catch (Exception exc)
            {
                ThrowFaultException("Getting file information failed.", exc);
            }
            return new List<FileEntry>();
        }

        public List<FileEntry> GetGeGucktFileInformation()
        {
            try
            {
                DirectoryInfo info = new DirectoryInfo(_pathSavetvNochZuGucken);

                var list = new List<FileEntry>();

                foreach (var file in info.EnumerateFiles("*.mp4", SearchOption.AllDirectories))
                {
                    list.Add(new FileEntry() { Name = file.Name, CreationTime = file.CreationTime, Path = file.FullName });
                }

                list.Sort(new Comparison<FileEntry>((x, y) =>
                {
                    return y.CreationTime.CompareTo(x.CreationTime);
                }));

                return list;
            }
            catch (Exception exc)
            {
                ThrowFaultException("Getting geguckt file information failed.", exc);
            }

            return null;
        }

        public void DeleteFileEntries(IEnumerable<FileEntry> filesToDelete)
        {
            try
            {
                if (filesToDelete != null)
                {
                    foreach (var fileEntry in filesToDelete)
                    {
                        File.Delete(fileEntry.Path);
                    }
                }
            }
            catch (Exception exc)
            {
                ThrowFaultException("Deleting files failed", exc);
            }
        }
    }
}
